<!DOCTYPE HTML>
<html>
<head>
<title>Boomerang 使用方法 #0: ビーコンや before_beacon イベントハンドラーからデータを取得する</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="../../boomerang-docs.css">
</head>
<body>
<span style="float:right;"><a href="../">ドキュメント一覧</a> | <a href="index.html">使用方法一覧</a></span>
<h1>Boomerang 使用方法 #0:<br>ビーコンや before_beacon イベントハンドラーからデータを取得する</h1>
<p>
これから説明する全ての例では、ビーコンや <code>before_beacon</code> イベントハンドラーから出力されるデータを取得する必要があります。このページではその使い方を説明します。
</p>

<h2>サーバーから返ってくるビーコンの結果</h2>
<p>
たいていの場合、パフォーマンスの結果をサーバーへ送って後で解析したり参考にできるようにしたいと思います。まず最初にやることはビーコンとして使う JavaScript で URL を設定することです。詳しい内容はこの後で紹介します。<code>BOOMR.init()</code> メソッドの <code>beacon_url</code> パラメーターを通してビーコンの URL を boomerang に伝えます:
</p>
<pre>
&lt;script src="boomerang.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
BOOMR.init({
		beacon_url: "http://yoursite.com/path/to/beacon.gif"
	});
&lt;/script&gt;
</pre>

<p>
例では beacon.gif が使用されていますが、実際は何でも構いません。同様にビーコンのハンドリングを PHP や C#、JSP などのスクリプトで書くこともできます。バックエンド上で何も起こらなかった場合はその URL を使用しバッチ処理でビーコンのパラメーターを取得するために apache のウェブログを後で調べましょう。
</p>

<h3>ビーコンのパラメーター</h3>
<p>
いくつかのパラメーターを保持してビーコンはサーバーへ送信されます。またそれぞれ独自のパラメーターを追加するプラグインも設定すれば、同様にパラメーターを取得できます。これは初期状態で取得できるものです:
</p>

<h4>boomerang のパラメーター</h4>
<dl>
<dt>v</dt> <dd>使用している boomerang のバージョン。</dd>
<dt>u</dt> <dd>ビーコンを送信したページの URL 。</dd>
</dl>

<h4>roundtrip プラグインのパラメーター</h4>
<dl>
<dt>t_done</dt> <dd><strong>[オプション]</strong> ページの往復時間。</dd>
<dt>t_page</dt> <dd><strong>[オプション]</strong> ページの先頭から page_ready までにかかった時間。開発時には必要になります。</dd>
<dt>t_resp</dt> <dd><strong>[オプション]</strong> ユーザーがリクエストを初期化してからレスポンスの最初のバイトまでにかかった時間。</dd>
<dt>t_other</dt> <dd><strong>[オプション]</strong> コンマで区切った開発者によって設定されたタイマーのリスト。いずれのタイマーも <code>name|value</code> の形式になります。</dd>
<dt>t_load</dt> <dd><strong>[オプション]</strong> ページがもし prerender の状態であれば、ページを fetch と prerender するために要した時間になります。</dd>
<dt>t_prerender</dt> <dd><strong>[オプション]</strong> ページがもし prerender の状態であれば、prefetch の開始からページが実際に表示されるまでの時間になります。これはデバッグ時に便利です。</dd>
<dt>t_postrender</dt> <dd><strong>[オプション]</strong> ページがもし prerender の状態であれば、prerender 後から実際にページが表示されるまでの時間になります。これはデバッグ時に便利です。</dd>
<dt>r</dt> <dd>ビーコンの開始時間を設定したページの URL 。</dd>
<dt>r2</dt> <dd><strong>[オプション]</strong> 現在のページのリファラーの URL 。<code>r</code> と <code>strict_referrer</code> が明らかに違う場合だけ設定します。</dd>
<dt>rt.start</dt> <dd>どこから開始するかを記述します。Cookie を開始するための <code>cookie</code> の1つや、W3C Navigation Timing API のための <code>navigation</code> や、Google Toolbar のための古い Chrome の <code>csi</code> や <code>gtb</code> などといったものになるでしょう。</dd>
</dl>

<h4>帯域幅と遅延プラグインのパラメーター</h4>
<dl>
<dt>bw</dt> <dd>秒間のバイト数で表したユーザーの帯域幅</dd>
<dt>bw_err</dt> <dd>測定エラーのマージンを省いた 95% 信頼できるユーザーの帯域幅</dd>
<dt>lat</dt> <dd>ミリ秒で表したユーザーの HTTP 遅延</dd>
<dt>lat_err</dt> <dd>測定エラーのマージンを省いた 95% 信頼できるユーザーの HTTP 遅延</dd>
<dt>bw_time</dt> <dd>帯域幅と遅延の測定が終わったときのユーザーのブラウザーのタイムスタンプ</dd>
</dl>

<h2>JavaScript からの結果の取得</h2>
<p>
ビーコンの結果がサーバーへ送信されない可能性があるため、あなたは JavaScript 内で自分でパフォーマンスの値を調べ、このデータをもとにいくつかの判断をしたいかもしれません。<code>before_beacon</code> イベントを登録することによってビーコンが発生する前のデータを取得できます。
</p>

<pre>
BOOMR.subscribe('before_beacon', function(o) {
	<span class="comment">// Do something with o</span>
});
</pre>

<p>
イベントハンドラーは1つのオブジェクトのパラメータと一緒に呼び出されます。このオブジェクトは上であげた <code>v</code> パラメーターを除く全てのビーコンのあらメーターを含んでいます。boomerang のバージョンを取得する場合は <code>BOOMR.version</code> を使用してください。
</p>

<p>
これ以降の全ての使用方法のドキュメントでは、<code>before_beacon</code> ハンドラーで以下のようなコードを使います:
</p>
<pre>
BOOMR.subscribe('before_beacon', function(o) {
	var html = "";
	if(o.t_done) { html += "This page took " + o.t_done + "ms to load&lt;br&gt;"; }
	if(o.bw) { html += "Your bandwidth to this server is " + parseInt(o.bw/1024) + "kbps (&amp;#x00b1;" + parseInt(o.bw_err*100/o.bw) + "%)&lt;br&gt;"; }
	if(o.lat) { html += "Your latency to this server is " + parseInt(o.lat) + "&amp;#x00b1;" + o.lat_err + "ms&lt;br&gt;"; }

	document.getElementById('results').innerHTML = html;
});
</pre>

<h2>バックエンドスクリプト</h2>
<p>
シンプルなバックエンドスクリプトはこのようになります。注意、あなたの環境外の URL パラメーターを取得するコードは含んでいないことに注意してください。使い方をすでに知っていると仮定しています。以下のコードはパラメーターは <code>params</code> という変数名になっていると仮定します。コードは JavaScript ですが、あなたの好きな言語で書くこともできます。
</p>

<pre>
function extract_boomerang_data(params)
{
	var bw_buckets = [64, 256, 1024, 8192, 30720],
	    bw_bucket = bw_buckets.length,
	    i, url, page_id, ip, ua, woeid;


	<span class="comment">// First validate your beacon, make sure all datatypes               </span>
	<span class="comment">// are correct and values within reasonable range                    </span>
	<span class="comment">// We'll also want to detect fake beacons, but that's more complex   </span>
	if(! validate_beacon(params)) {
		return false;
	}

	<span class="comment">// You may also want to do some kind of random sampling at this point</span>

	<span class="comment">// Figure out a bandwidth bucket.                                    </span>
	<span class="comment">// we could get more complex and consider bw_err as well,            </span>
	<span class="comment">// but for this example I'll ignore it                               </span>
	for(i=0; i&lt;bw_buckets.length; i++) {
		if(params.bw &lt;= bw_buckets[i]) {
			bw_bucket = i;
			break;
		}
	}

	<span class="comment">// Now figure out a page id from the u parameter                     </span>
	<span class="comment">// Since we might have a very large number of URLs that all          </span>
	<span class="comment">// map onto a very small number (possibly 1) of distinct page types  </span>
	<span class="comment">// It's good to create page groups to simplify performance analysis. </span>

	url = canonicalize_url(params.u); <span class="comment">// get a canonical form for the URL</span>
	page_id = get_page_id(url);	  <span class="comment">// get a page id.  (many-&gt;1 map?)  </span>


	<span class="comment">// At this point we can extract other information from the request   </span>
	<span class="comment">// eg, the user's IP address (good for geo location) and user agent  </span>
	ip = get_user_ip();              <span class="comment">// get user's IP from request       </span>
	woeid = ip_to_woeid(ip);         <span class="comment">// convert IP to a Where on earth ID</span>
	ua = get_normalized_uastring();	 <span class="comment">// get a normalized useragent string</span>

	<span class="comment">// Now insert the data into our database                             </span>
	insert_data(page_id, params.t_done, params.bw, params.bw_err, bw_bucket, params.lat, params.lat_err, ip, woeid, ua);

	return true;
}
</pre>

<h3>スケールアップ</h3>
<p>
上記のコードは1日に数千のリクエストがある場合に適しています。その数が数千、数百万と増える場合、ビーコンのハンドラーはすぐにボトルネックとなります。そういった場合はビーコンを単純にバッチ処理にすることができます。リクエストは apache のログに残り、定期的にそれらのログをバッチ処理によってデータベースに挿入します。
</p>
<p>
<a href="http://www.slideshare.net/bluesmoon/scaling-mysql-writes-through-partitioning-ipc-spring-edition">scaling MySQL writes</a> は MySQL を使った大きなビーコンの結果のハンドリングの仕方について IPC Berlin 2010 で話したときの資料です。いい解決方法への参考になるかもしれません。
</p>

<h2>データの統計解析</h2>
<p>
データを取得できると、その解析した統計があると便利です。これは今後の使用方法で説明しますが、今のところ <a href="http://www.slideshare.net/bluesmoon/index-3441823">the statistics of web performance</a> の ConFoo 2010 の資料が参考になると思います。
</p>

<p class="perma-link">
最新のソースコードとドキュメントは <a href="http://github.com/lognormal/boomerang/">github.com/lognormal/boomerang</a> に公開されています。
</p>

<p id="results">
</p>

<script src="../../../boomerang.js" type="text/javascript"></script>
<script src="../../howtos/howtos.js" type="text/javascript"></script>
<script type="text/javascript">
BOOMR.init({
		user_ip: '10.0.0.1',
		BW: {
			base_url: '../../images/',
			cookie: 'HOWTO-BA'
		},
		RT: {
			cookie: 'HOWTO-RT'
		}
	});
</script>
</body>
</html>
<!--
    Copyright (c) 2011, Yahoo! Inc.  All rights reserved.
    Copyrights licensed under the BSD License. See the accompanying LICENSE.txt file for terms.
-->
